package app.vendorportal;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import core.framework.crypto.EncryptionUtils;
import core.framework.database.JDBCAccess;
import core.framework.database.JPAAccess;
import core.framework.util.ClasspathResource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;

import javax.inject.Inject;
import javax.inject.Named;
import javax.sql.DataSource;
import java.beans.PropertyVetoException;

@Configuration
public class DBConfig {

    public static final String JDBC_TRANSACTION_MANAGER = "jdbcTransactionManager";
    @Inject
    Environment env;

    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory() throws PropertyVetoException {
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(dataSource());
        factoryBean.setPackagesToScan(DBConfig.class.getPackage().getName());
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setDatabase(Database.MYSQL);
        vendorAdapter.setShowSql(false);
        vendorAdapter.setGenerateDdl(false);
        factoryBean.setJpaVendorAdapter(vendorAdapter);
        return factoryBean;
    }

    @Bean(destroyMethod = "close")
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl(env.getRequiredProperty("jdbc.url"));
        dataSource.setUser(env.getRequiredProperty("jdbc.username"));
        dataSource.setPassword(EncryptionUtils.decrypt(env.getRequiredProperty("jdbc.password"), new ClasspathResource("private-key.pem")));

        dataSource.setTestConnectionOnCheckout(true);
        dataSource.setPreferredTestQuery("select 1");

        dataSource.setMaxPoolSize(env.getRequiredProperty("pool.max.size", Integer.class));
        dataSource.setMinPoolSize(env.getRequiredProperty("pool.min.size", Integer.class));

        //dataSource.setConnectionCustomizerClassName(IsolationLevelConnectionCustomizer.class.getName());

        return dataSource;
    }

    @Primary
    @Bean
    public PlatformTransactionManager transactionManager() throws PropertyVetoException {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }

    @Bean
    @Named(value = JDBC_TRANSACTION_MANAGER)
    public PlatformTransactionManager jdbcTransactionManager() throws PropertyVetoException {
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource());
        return transactionManager;
    }

    @Bean
    public JPAAccess jpaAccess() {
        return new JPAAccess();
    }

    @Bean
    public JDBCAccess jdbcAccess() throws PropertyVetoException {
        JDBCAccess jdbcAccess = new JDBCAccess();
        jdbcAccess.setDataSource(dataSource());
        return jdbcAccess;
    }

}
